home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Very Best of Atari Inside
/
The Very Best of Atari Inside 1.iso
/
mint
/
mfs055
/
minit.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-26
|
13KB
|
553 lines
/* minit Minix INITializer . Freely distributable Minix filesys creator.
* Copyright S N Henson Nov 1991 .
* Use entirely at your own risk ! If it trashes your hard-drive then
* it isn't my fault !
*/
/* Version 0.211 */
/* Compile with gcc -O -o minit.ttp minit.c -liio */
#include <osbind.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
/* New extended Rwabs function , same as Rwabs except sectors can
* be specified as longs , this will be needed for large V2 filesystems.
* you will need to change this for other compilers ....
*/
#define _XRwabs(a,b,c,d,e,f) \
trap_13_wwlwwwl((short)(0x04),(short)(a),(long)(b),(short)(c),(short)(d)\
,(short)(e),(long)(f) )
#define trap_13_wwlwwwl(n, a, b, c, d, e, f) \
({ \
register long retvalue __asm__("d0"); \
volatile short _a = (volatile short)(a); \
volatile long _b = (volatile long) (b); \
volatile short _c = (volatile short)(c); \
volatile short _d = (volatile short)(d); \
volatile short _e = (volatile short)(e); \
volatile long _f = (volatile long) (f); \
\
__asm__ volatile \
("\
movl %5,sp@-; \
movw %4,sp@-; \
movw %3,sp@-; \
movw %2,sp@-; \
movl %1,sp@-; \
movw %0,sp@- " \
: /* outputs */ \
: "g"(_a), "g"(_b), "g"(_c), "g"(_d), "g"(_e), "g"(_f) /* inputs */ \
); \
\
__asm__ volatile \
("\
movw %1,sp@-; \
trap #13; \
addw #18,sp " \
: "=r"(retvalue) /* outputs */ \
: "g"(n) /* inputs */ \
: "d0", "d1", "d2", "a0", "a1", "a2" /* clobbered regs */ \
); \
retvalue; \
})
/* Change this if needed , but only if you know what you are doing */
/* You shouldn't need to with the -n option though */
#define MNAME_MAX 14
int shift,drive=-1;
long numblocks,numinodes,incr=1;
/* various flags */
char protect,sonly,zbpb,v2,lrecno,tst;
unsigned char block_buf[1024];
/* Structures we will need */
typedef struct {
unsigned short s_ninodes; /* # usable inodes on the minor device */
unsigned short s_nzones; /* total device size, including bit maps etc */
unsigned short s_imap_blks; /* # of blocks used by inode bit map */
unsigned short s_zmap_blks; /* # of blocks used by zone bit map */
unsigned short s_firstdatazn; /* number of first data zone */
short int s_log_zsize; /* log2 of blocks/zone */
unsigned long s_max_size; /* maximum file size on this device */
short s_magic; /* magic number to recognize super-blocks */
short pad; /* padding */
long s_zones; /* equivalent to 's_nzones' for V2 */
} super_block;
typedef struct { /* directory entry */
unsigned short d_inum; /* inode number */
char d_name[MNAME_MAX]; /* character string */
} dir_struct;
typedef struct { /* disk inode. */
unsigned short i_mode; /* file type, protection, etc. */
unsigned short i_uid; /* user id of the file's owner */
unsigned long i_size; /* current file size in bytes */
unsigned long i_mtime; /* when was file data last changed */
unsigned char i_gid; /* group number */
unsigned char i_nlinks; /* how many links to this file */
unsigned short i_zone[9]; /* block nums for direct, ind, and dbl ind */
} d_inode;
typedef struct {
unsigned short i_mode;
unsigned short i_nlinks;
unsigned short i_uid;
unsigned short i_gid;
unsigned long i_size;
unsigned long i_atime;
unsigned long i_mtime;
unsigned long i_ctime;
long i_zone[10];
} d_inode2;
/* prototypes */
#ifdef __STDC__
# define P(s) s
#else
# define P(s) ()
#endif
int main P((int argc , char **argv ));
int nrwabs P((int rw , void *buf , unsigned count , long recno , int drive ));
void get_block P((long num ));
void put_block P((long num ));
void check_lrecno P((void ));
int warn P((void ));
#undef P
main(argc,argv)
int argc;
char **argv;
{
extern int optind,opterr;
extern char *optarg;
int c ;
static char err=0;
int i,j;
unsigned short *bpb;
unsigned short ioff,zone1;
super_block *sblk=(super_block *)block_buf,csblk;
d_inode *rip=(d_inode *)block_buf;
d_inode2 *ripn=(d_inode2 *)block_buf;
dir_struct *dir=(dir_struct *)block_buf;
unsigned short *srt=(unsigned short *)block_buf;
/* Parse command-line options */
opterr=0;
while((c=getopt(argc,argv,"b:B:i:I:n:pPSZtV"))!=EOF)
{
switch(c){
case 'B':
case 'b':
numblocks=atol(optarg);
break;
case 'n':
incr=atol(optarg);
break;
case 'i':
case 'I':
numinodes=atol(optarg);
break;
case 'P':
protect=1;
break;
case 'p':
protect=2;
break;
case 'S':
sonly=1;
break;
case 'Z':
zbpb=1;
break;
case 'V':
v2=1;
break;
case 't':
tst=1;
break;
case '?':
err=1;
break;
}
}
if(argc-optind!=1 || err || (zbpb && protect) )
{
fprintf(stderr,"Minix-compatible filesystem initializer\n");
fprintf(stderr,"Copyright S N Henson Nov 1991\n");
fprintf(stderr,"Version 0.211\n");
fprintf(stderr,"Usage\t(auto)\t: minit drive\n");
fprintf(stderr,"\t(manual): minit -b blocks -i inodes drive\n");
fprintf(stderr,"Also :\t-S only write out super-block\n");
fprintf(stderr,"\t-P protect filesystem with null disk\n");
fprintf(stderr,"\t-p make null disk of existing filestystem\n");
fprintf(stderr,"\t-Z protect with zero BPB\n");
fprintf(stderr,"\t-V make a V2 filesystem\n");
fprintf(stderr,"\t-n dirincrement\n");
fprintf(stderr,"\t-t test for lrecno in driver software\n");
exit(1);
}
drive=(argv[optind][0] & ~32)-'A' ;
/* Sanity checking time */
if((incr < 1) || (incr > 16) || ( (incr) & (incr-1) ) )
{
fprintf(stderr,"Dirincrement must be a power of two between\n");
fprintf(stderr,"1 and 16 (inclusive)\n");
exit(1);
}
if( (numinodes < 0) || (numinodes > 65535) )
{
fprintf(stderr,"Need at least 1 and no more than 65535 inodes\n");
exit(1);
}
if(!(bpb=Getbpb(drive))) {
fprintf(stderr,"Drive %c : Bad or illegal BPB\n",drive+'A');
exit(1);
}
if(bpb[0]!=512 && bpb[0]!=1024) {
fprintf(stderr,"Sorry unsupported sector size: %d\n",bpb[0]);
exit(1);
}
if(bpb[0]==512)shift=1;
else if(protect)
{
fprintf(stderr,"Null disk requires 512 byte sectors\n");
exit(1);
}
if(drive > 1 ) check_lrecno();
if(tst)
{
if(lrecno) fprintf(stderr,"Lrecno supported by this setup\n");
else fprintf(stderr,"Lrecno not supported by this setup\n");
exit(0);
}
/* Work out parameters */
get_block(0); /* Read in boot sector */
/* Get filesys size from bootsector if not given */
if(numblocks==0)
{
numblocks=(block_buf[19]+( ((long)block_buf[20])<<8))>>shift;
if(numblocks < 40 ){
fprintf(stderr,"%ld blocks ? Is that bootsector OK ?\n",numblocks);
exit(1);
}
}
if(!v2 && (numblocks > 65535) ) {
fprintf(stderr,"V1 filesystems can be at most 65535 blocks\n");
exit(1);
}
if( !lrecno && (numblocks > 65535) ) {
fprintf(stderr,"Filesystems bigger than 64MEG require lrecno\n");
exit(1);
}
if( !lrecno && shift && (numblocks > 32767) ) {
fprintf(stderr,"Filesytems bigger than 32MEG require 1K sectors\n");
exit(1);
}
get_block(numblocks-1); /* Try to read last block */
if(numinodes==0)
{
numinodes = numblocks/3;
/* Round up inode number to nearest block */
if(v2) numinodes = (numinodes + 15) & ~15;
else numinodes=(numinodes + 31 ) & ~31;
}
if(numinodes > 65535) numinodes=65535;
if(protect==2)
{
get_block(1);
if( (sblk->s_magic != 0x137f) && (sblk->s_magic!=0x2468) )
{
fprintf(stderr,"Fatal: bad magic number\n");
exit(1);
}
}
warn();
/* Set up boot sector */
if(!sonly && (protect || zbpb) )
{
get_block(0);
if(protect)
{
/* Make GEMDOS think we have a tiny partition */
/* With root directory immediately after super-block */
block_buf[16]=2;
block_buf[17]=16;
block_buf[18]=0;
block_buf[22]=1;
block_buf[23]=0;
}
else if(zbpb)
{
block_buf[16]=block_buf[17]=block_buf[18]=0;
block_buf[22]=block_buf[23]=0;
}
strcpy((char *)(&block_buf[2]),"MINIX");
put_block(0);
}
/* OK lets work out some stuff */
if(protect==2) get_block(1);
else
{
bzero(block_buf,1024l);
/* Super block */
sblk->s_ninodes=numinodes;
if(v2) sblk->s_zones=numblocks;
else sblk->s_nzones=numblocks;
sblk->s_imap_blks=(numinodes+8192)/8192;
sblk->s_zmap_blks=(numblocks+8191)/8192;
sblk->s_firstdatazn=2+sblk->s_imap_blks+sblk->s_zmap_blks
+ ( v2 ? ((numinodes+15)/16) : ((numinodes+31)/32)) ;
sblk->s_log_zsize=0;
sblk->s_max_size= v2 ? 0x4041c00l : 0x10081c00l;
sblk->s_magic= v2 ? 0x2468 : 0x137f;
}
/* If protecting fill up the pseudo root directory with vol names */
if(protect)
{
bzero(&block_buf[512],512);
for(i=512;i<1024;i+=32)
{
strncpy((char*)&block_buf[i],"MINIXFS ",11);
block_buf[i+11]=0x08;
}
}
put_block(1);
if( sonly || protect==2 ) exit(0);
csblk=*sblk;
ioff=2+sblk->s_imap_blks+sblk->s_zmap_blks;
zone1=sblk->s_firstdatazn;
bzero(block_buf,1024l);
/* Inode bitmaps */
for(i=2;i<2+csblk.s_imap_blks;i++)
{
long icount=numinodes+1;
if(i==2)
{
srt[0]=3;
}
if(icount < 8192) /* Need to mark dead inodes as used */
{
if(icount & 15)
{
srt[icount/16] = 0xffff << (icount & 15);
icount+= 16 - (icount & 15);
}
for(j=icount/16;j<512;j++)srt[j]=0xffff;
}
put_block(i);
if(i==2)srt[0]=0;
icount-=8192;
}
bzero(block_buf,1024l);
/* Zone bitmaps */
for(i=2+csblk.s_imap_blks;i<ioff;i++)
{
long zcount=numblocks+1-csblk.s_firstdatazn;
if(i==2+csblk.s_imap_blks)
{
srt[0]=3;
}
if(numblocks < 8192) /* Need to mark dead zones as used */
{
if(zcount & 15)
{
srt[zcount/16] = 0xffff << (zcount & 15);
zcount+= 16 - (zcount & 15);
}
for(j=zcount/16;j<512;j++)srt[j]=0xffff;
}
put_block(i);
if(i==2+csblk.s_imap_blks)srt[0]=0;
zcount-=8192;
}
bzero(block_buf,1024l);
/* Initialise inodes */
for(i=ioff;i<ioff+
(v2 ? ((numinodes +15)/16) : ((numinodes+31)/32 )) ;i++)
{
if(i==ioff) /* Root inode , initialise it properly */
{
if(v2)
{
ripn->i_mode=040777; /* Directory */
ripn->i_size=32*incr;
ripn->i_mtime=time((time_t *)0);
ripn->i_ctime=ripn->i_mtime;
ripn->i_atime=ripn->i_mtime;
ripn->i_nlinks=2;
ripn->i_zone[0]=zone1;
}
else
{
rip->i_mode=040777; /* Directory */
rip->i_size=32*incr;
rip->i_mtime=time((time_t *)0);
rip->i_nlinks=2;
rip->i_zone[0]=zone1;
}
}
put_block(i);
if(i==ioff)bzero(block_buf,1024l);
}
bzero(block_buf,1024l);
/* And finally the root directory */
dir[0].d_inum=1;
strcpy(dir[0].d_name,".");
dir[incr].d_inum=1;
strcpy(dir[incr].d_name,"..");
put_block(zone1);
fprintf(stderr,"Initialised OK.\n");
fprintf(stderr,"%ld Blocks , %ld Inodes.\n",numblocks,numinodes);
exit(0);
}
int nrwabs(rw,buf,count,recno,dev)
int rw;
void *buf;
unsigned count;
long recno;
int dev;
{
if(lrecno && (dev > 1) )
return (_XRwabs(rw,buf,count,-1,dev,recno) );
else return (Rwabs(rw,buf,count,(unsigned)(recno),dev) );
}
void get_block(num)
long num;
{
if(nrwabs(2,block_buf,1<<shift,num<<shift,drive))
{
fprintf(stderr,"Fatal Read Error block %d\n",num);
exit(0);
}
}
void put_block(num)
long num;
{
if(nrwabs(3,block_buf,1<<shift,num<<shift,drive))
{
fprintf(stderr,"Fatal Write Error block %d\n",num);
exit(0);
}
}
/* entirely unoffical attempt to check for the existance of 'lrecno' */
char block_buf2[1024];
void check_lrecno()
{
/* read in boot block */
if(Rwabs(2,block_buf,1<<shift,0,drive)) return;
/* read it in with lrecno */
if( _XRwabs(2,block_buf2,1<<shift,-1,drive,0l) ) return;
/* Compare the two */
if(bcmp(block_buf,block_buf2,1024)) return;
/* read in next sector with lrecno */
if(_XRwabs(2,block_buf2,1<<shift,-1,drive,1l)) return;
/* compare the two */
if(!bcmp((char *)block_buf,block_buf2,1024)) return;
lrecno=1;
return;
}
warn()
{
int ch;
fprintf(stderr,"WARNING ! THIS %s TOTALLY DESTROY ANY DATA ON ",
(sonly || protect) ? "MAY":"WILL");
fprintf(stderr,"DRIVE %c !\n",drive+'A');
fprintf(stderr,"Are you ABSOLUTELY SURE you want to do this (y/n)?\n");
ch=Crawcin() & 0xff ;
if(ch!='Y' && ch!='y')
{
fprintf(stderr,"Aborted\n");
exit(0);
}
}